#include <BME82M131.h>
#include <RTClib.h>
#include "ONENET.h"
#include <BM25S2021-1.h>
#include <Servo.h>
BM25S2021_1 BMht(&Wire1);
BMC81M001       Wifi(&Serial4); 
Servo servo;                   //舵机     90度为开盖，180度关盖
String Data_String="Hello";
int Data_int=50,Data_int_min=30,Data_int_max=80,light_int=50,dan_int=1,lin_int=1,jia_int=1,tu_int=30;
float Temperature=27.5,Temperature_min=15,Temperature_max=40;
int tu_Data=50,tu_Data_min=30,N,N_min,P,P_min,K,K_min;
BME82M131 ALS;           //Create a BME82M131 object
char pub[300];
String dat;
const int dataSize = 12; // 假设数据包有10个字节
byte dataBytes[dataSize];

unsigned long previousMillisTask1 = 0;  // 上次任务1执行的时间
unsigned char ii=0;
const long intervalTask1 = 10000;       // 任务1的执行间隔（10秒）
int lastServoPosition = -1; // 上一次舵机的位置
int lastRainState = HIGH; // 上一次引脚 3 的状态
void setup() {
  ALS.begin();
  Serial3.begin(9600);
  pinMode(3, INPUT);
  pinMode(8, OUTPUT);//加湿器
  servo.attach(9);  //io 9 用作舵机
  pinMode(10, OUTPUT);//风扇
  pinMode(11, OUTPUT);//加热
  pinMode(12, OUTPUT);//制冷
  pinMode(13, OUTPUT);//灯

  pinMode(14, OUTPUT);//土壤湿度
  pinMode(15, OUTPUT);//氮
  pinMode(16, OUTPUT);//磷
  pinMode(17, OUTPUT);//钾
  BMht.begin();
  Serial.begin(9600);
  wifi_init();
}


void loop() {
  unsigned long currentMillis = millis();  // 获取当前时间
  // 检查是否达到任务1的执行间隔
  if (currentMillis - previousMillisTask1 >= intervalTask1) {
    previousMillisTask1 = currentMillis;
    if(ii==0){
    Serial.println("Task 1 executed");
    sent1();
    delay(10);
    wifi_sent1(); 
    rain_sensor();
    tem_control();
    tu_tem_control();
    ii=1;}
    else{
    Serial.println("Task 2 executed");
    sent2();
    delay(10);  
    wifi_sent2();
    ii=0;}
  }
    wifi_rece();
}

//检测有雨关闭顶盖
void rain_sensor() {
  int currentRainState = digitalRead(3); // 当前引脚 3 的状态
  // 如果引脚状态发生变化
  if (currentRainState != lastRainState) {
    lastRainState = currentRainState; // 更新上一次引脚状态
    int targetPosition = (currentRainState == HIGH) ? 90 : 180; // 根据引脚状态设置目标位置
    // 如果目标位置与上一次舵机位置不同，则更新舵机位置
    if (targetPosition != lastServoPosition) {
      servo.write(targetPosition); // 更新舵机位置
      lastServoPosition = targetPosition; // 更新上一次舵机位置
    }
  }
}

//加减温湿度控制
void tem_control() {
  //超出湿度，打开风扇
  if (Data_int > Data_int_max) {
    digitalWrite(10, HIGH);
  }
  //低于湿度，打开加湿器
  else if (Data_int < Data_int_min) {
    digitalWrite(8, HIGH);
  }
  else {
    digitalWrite(10, LOW);   
    digitalWrite(8, LOW);
  }
  //高于温度，打开制冷器
  if (Temperature > Temperature_max) {
    digitalWrite(12, HIGH);
  } 
  //低于温度，打开加热器
  else if (Temperature < Temperature_min) {
      digitalWrite(11, HIGH);
  }
  else {
    digitalWrite(12, LOW);   
    digitalWrite(11, LOW);
  }
}

//土壤湿度氮磷钾控制
void tu_tem_control() {
  //缺水，打开抽水
  if (tu_Data < tu_Data_min) {
    digitalWrite(14, HIGH);
  }
  else {  
    digitalWrite(14, LOW);
  }
  //高于温度，打开制冷器
  if (N < N_min) {
    digitalWrite(15, HIGH);
  } 
  else {  
    digitalWrite(15, LOW);
  }
  if (P < P_min) {
    digitalWrite(16, HIGH);
  } 
  else {  
    digitalWrite(16, LOW);
  }
  if (K < K_min) {
    digitalWrite(17, HIGH);
  } 
  else {  
    digitalWrite(17, LOW);
  }

}

//初始化wifi
void wifi_init()   
{
  Wifi.begin();
  Wifi.reset(); 
  Serial.print("WIFI Connection Results:");
  if(Wifi.connectToAP(WIFI_SSID,WIFI_PASS)==0) 
  {
    Serial.println("fail");
  } 
  else {Serial.println("success");}
  Serial.print("ONENET Connection Results:");
  if(Wifi.configMqtt(CLIENTLID,USERNAME,PASSWORD,MQTT_HOST,SERVER_PORT)==0)
  {
    Serial.println("fail");
  }
  else {Serial.println("success");}
  delay(200);
  Wifi.setSubscribetopic(ONENET_TOPIC_PROP_SET);
  Wifi.setSubscribetopic(ONENET_TOPIC_PROP_GET);
  Wifi.setSubscribetopic(ONENET_TOPIC_PROP_GET_REPLY);
  //Wifi.setSubscribetopic(ONENET_TOPIC_PROP_SET_REPLY);
  Wifi.setSubscribetopic(ONENET_TOPIC_PROP_POST_REPLY);
}
//更新温湿度、加上光强
void read_temp_humi()   
{
  Temperature=BMht.readTemperature();
  Data_int=BMht.readHumidity();
  light_int=ALS.readLux(1);
}
//wifi上传数据到云端
void wifi_sent1()
{
    read_temp_humi();
    String temp=String(Temperature,1);
    SET_BUF = "{\"id\":\"";
    SET_BUF += ID;
    ID++;
    SET_BUF += "\",\"version\":\"1.0\",\"params\":{\"temp\":{\"value\":";
    SET_BUF += temp;  
    SET_BUF += "},\"humi\":{\"value\":";
    SET_BUF += Data_int;  
    SET_BUF += "},\"String\":{\"value\":\"";
    SET_BUF += Data_String; 
    SET_BUF += "\"},\"hmin\":{\"value\":";
    SET_BUF += Data_int_min;  
    SET_BUF += "},\"hmax\":{\"value\":";
    SET_BUF += Data_int_max; 
    SET_BUF += "},\"light\":{\"value\":";
    SET_BUF += light_int; 
    SET_BUF += "},\"tmin\":{\"value\":";
    SET_BUF += Temperature_min;  
    SET_BUF += "},\"tmax\":{\"value\":";
    SET_BUF += Temperature_max;  
    SET_BUF += "}}}";
    SET_BUF.toCharArray(pub,SET_BUF.length()+1);
    if(Wifi.writeBytes(pub,SET_BUF.length(),ONENET_TOPIC_PROP_POST))
      {
        Serial.println("Send String data sucess");       
      }
}

//wifi上传数据到云端
void wifi_sent2()
{
    SET_BUF = "{\"id\":\"";
    SET_BUF += ID;
    ID++;
    SET_BUF += "\",\"version\":\"1.0\",\"params\":{\"dan\":{\"value\":";
    SET_BUF += dan_int;
    SET_BUF += "},\"jia\":{\"value\":";
    SET_BUF += jia_int;
    SET_BUF += "},\"lin\":{\"value\":";
    SET_BUF += lin_int;
    SET_BUF += "},\"tu\":{\"value\":";
    SET_BUF += tu_int;
    SET_BUF += "}}}";
    SET_BUF.toCharArray(pub,SET_BUF.length()+1);
    if(Wifi.writeBytes(pub,SET_BUF.length(),ONENET_TOPIC_PROP_POST))
      {
        Serial.println("Send String data sucess");       
      }
}


//处理上位机下发的命令
void wifi_rece()
{
    unsigned char t=0,t1=0;
    Wifi.readIotData(&ReciveBuff,&ReciveBufflen,&topic);
    if(Wifi.OneNetReciveBuff.length()>5)
    {
      String message = Wifi.OneNetReciveBuff;
      Serial.println(message);
      int jsonStart = message.indexOf('{');
      int jsonEnd = message.lastIndexOf('}');
      String jsonString = message.substring(jsonStart, jsonEnd + 1);
      StaticJsonDocument<128> doc;
      DeserializationError error = deserializeJson(doc, jsonString);
      if (!error) {
    // 提取params中的String值
      if (doc["params"]["String"].is<String>()) {
      dat = doc["params"]["String"].as<String>();
      Serial.println("Extracted value: " + dat);
      t=1;
      t1=1;
      }}
      if(t==1){
      StaticJsonDocument<128> response;
      response["id"] = doc["id"];
      response["code"] = 200;
      response["msg"] = "success";
      String responseStr;
      serializeJson(response, responseStr);
      // 发送响应消息
      char responsePub[200];
      responseStr.toCharArray(responsePub, sizeof(responsePub));
      Wifi.writeBytes(responsePub, responseStr.length(),ONENET_TOPIC_PROP_SET_REPLY);
      Serial.println("Response sent");
      t=0;
      }}
    if(t1==1){
    int datInt = dat.toInt(); // dat是一个String类型
    switch (datInt) {
    case 1: digitalWrite(13, HIGH); break;
    case 0: digitalWrite(13, LOW); break;
    // 湿度
    case 2: if (Data_int_min < 50)  Data_int_min += 2; break;
    case 3: if (Data_int_min > 0)   Data_int_min -= 2; break;
    case 4: if (Data_int_max < 100) Data_int_max += 2; break;
    case 5: if (Data_int_max > 50)  Data_int_max -= 2; break;
    // 温度
    case 6: if (Temperature_min < 30) Temperature_min += 1; break;
    case 7: if (Temperature_min > -30) Temperature_min -= 1; break;
    case 8: if (Temperature_max < 100) Temperature_max += 1; break;
    case 9: if (Temperature_max > 30) Temperature_max -= 1; break;
    default: break;
}
    t1=0;
}
    clearBuff();
//  delay(1000);
}
void clearBuff()
{
  memset(pub,'\0',200);
  resLen = 0;
  Wifi.OneNetReciveBuff="0";
}

// 土壤温湿度
void sent1() {
  static byte data[] = {0x01, 0x03, 0x00, 0x12, 0x00, 0x02, 0x64, 0x0e};
  Serial3.write(data, sizeof(data));
}

// 氮钾磷
void sent2() {
  static byte data[] = {0x01, 0x03, 0x00, 0x1e, 0x00, 0x03, 0x65, 0xcd};
  Serial3.write(data, sizeof(data));
}

void handleReceivedData1(byte dataBytes[]) {
  byte address = dataBytes[0];
  byte function = dataBytes[1];
  byte byteCount = dataBytes[2];
  byte humidityHigh = dataBytes[3];
  byte humidityLow= dataBytes[4];
  byte tempHigh = dataBytes[5];
  byte tempLow= dataBytes[6];
  byte checksumLow = dataBytes[7];
  byte checksumHigh = dataBytes[8];
unsigned int a = (humidityHigh<<8)|humidityLow;
 tu_int = a*0.1;
  // 打印处理后的数据
  Serial.print("Address: 0x");
  Serial.print(address, HEX);
  Serial.print(", Function: 0x");
  Serial.print(function, HEX);
  Serial.print("humidity: ");
  Serial.print(tu_int);
  Serial.println(" %");
}

void handleReceivedData2(byte dataBytes[]) {
  byte address = dataBytes[0];
  byte function = dataBytes[1];
  byte byteCount = dataBytes[2];
  byte danHigh = dataBytes[3];
  byte danLow= dataBytes[4];
  byte linHigh = dataBytes[5];
  byte linLow= dataBytes[6];
  byte jiaHigh = dataBytes[7];
  byte jiaLow= dataBytes[8];
  byte checksumLow = dataBytes[9];
  byte checksumHigh = dataBytes[10];
 dan_int = (danHigh<<8)|danLow;
 lin_int = (linHigh<<8)|linLow;
 jia_int = (jiaHigh<<8)|jiaLow;

  // 打印处理后的数据
  Serial.print("Address: 0x");
  Serial.print(address, HEX);
  Serial.print(", Function: 0x");
  Serial.print(function, HEX);
  Serial.print("dan: ");
  Serial.print(dan_int);
  Serial.print("lin: ");
  Serial.print(lin_int);
  Serial.print("jia: ");
  Serial.print(jia_int);
}


void serialEvent3() {
  // 当串口3接收到数据时，这个函数将被调用
  int availableBytes = Serial3.available(); // 获取当前可用的字节数
// Serial.println(availableBytes);
  if (availableBytes == 9){
  Serial3.readBytes(dataBytes, 9);

      // 打印接收到的数据，用于调试
      Serial.print("Received 9-byte data: ");
      for (int i = 0; i < 9; i++) {
        Serial.print(dataBytes[i], HEX);
        Serial.print(" ");
      }
      Serial.println("ok1");

      // 在这里处理接收到的9字节数据
      handleReceivedData1(dataBytes);}
  else if (availableBytes == 11){
  Serial3.readBytes(dataBytes, 11);

      // 打印接收到的数据，用于调试
      Serial.print("Received 11-byte data: ");
      for (int i = 0; i < 11; i++) {
        Serial.print(dataBytes[i], HEX);
        Serial.print(" ");
      }
      Serial.println("ok2");

      // 在这里处理接收到的11字节数据
      handleReceivedData2(dataBytes);}
}
